package com.dyb.demo.algorithm;

import java.util.stream.IntStream;

/**
 * 金额分摊
 *  1	2	3	4
 *
 * 	2	2	2	2	2		1
 * 	1	2	2	2	2		2
 * 	1	0	2	2	2		3 -> 1
 * 	1	0	0	2	2		1
 * 	0	0	0	2	2		4 -> 2
 * 	0	0	0	0	2		2
 * 	0	0	0	0	0
 * @author evandong
 */
public class AmtProportion {


    public static void main(String[] args) {
        // 单据金额，发票金额
        int[] order = new int[]{1, 2, 3, 1, 100};
        int[] invoice = new int[] {2, 2, 2, 2, 2};

        int orderSum = IntStream.of(order).sum();
        int invoiceSum = IntStream.of(invoice).sum();

        // order invoice容差正负100
        assert Math.abs(orderSum - invoiceSum) <= 100;

        String[][] result = loopOrder(order, invoice);

        printArray(result);
        printArray(order);
        printArray(invoice);
    }

    private static String[][] loopOrder(int[] order, int[] invoice) {
        String[][] result = new String[order.length][2];
        // 匹配
        for (int i = 0; i < order.length; i++) {
            int o = order[i];
            // 最小容差值
            // Integer min = null;
            int inv_index = loopInvoice(o, invoice);
            // 筛选订单与发票比对最小容差
            /*for (int j = 0; j < invoice.length; j++) {
                int inv = invoice[j];
                if(inv == 0) continue;
                if (min == null) {
                    // 初始化min
                    min = Math.abs(inv - o);
                    // 记录下标
                    inv_index = j;
                    // 订单金额与发票打平，跳出比较
                    if (min == 0) break;
                } else {
                    int a;
                    if ((a = Math.abs(inv - o)) < min) {
                        min = a;
                        // 记录下标
                        inv_index = j;
                        // 订单金额与发票打平，跳出比较
                        if (min == 0) break;
                    }
                }
            }*/
            if (inv_index == 0 && invoice[inv_index] == 0) continue;
            int c = o - invoice[inv_index];
            if (c == 0) {
                result[i][0] = append(result, i, 0, o+",");
                result[i][1] = append(result, i, 1,invoice[inv_index] + ",");
                System.out.println(i +": "+ inv_index);
                order[i] = 0;
                invoice[inv_index] = 0;
            }
            else if (c > 0) {
                result[i][0] = append(result, i, 0, o+",");
                result[i][1] = append(result, i, 1,invoice[inv_index] + ",");
                System.out.println(i +": "+ inv_index);
                // 订单金额>发票金额，订单金额再分配
                order[i] = c;
                invoice[inv_index] = 0;

                // 回退再分配
                i--;
            }
            else {
                result[i][0] = append(result, i, 0, o+",");
                result[i][1] = append(result, i, 1,invoice[inv_index] + ",");

                System.out.println(i +": "+ inv_index);

                // 订单金额<发票金额，剩余发票金额放入待分配区域
                order[i] = 0;
                invoice[inv_index] = Math.abs(c);
            }
        }

        return result;
    }

    private static int loopInvoice(int o, int[] invoice) {
        // 最小容差值
        Integer min = null;
        int inv_index = 0;

        for (int j = 0; j < invoice.length; j++) {
            int inv = invoice[j];
            if(inv == 0) continue;
            if (min == null) {
                // 初始化min
                min = Math.abs(inv - o);
                // 记录下标
                inv_index = j;
                // 订单金额与发票打平，跳出比较
                if (min == 0) break;
            } else {
                int a;
                if ((a = Math.abs(inv - o)) < min) {
                    min = a;
                    // 记录下标
                    inv_index = j;
                    // 订单金额与发票打平，跳出比较
                    if (min == 0) break;
                }
            }
        }

        return inv_index;
    }

    private static String append(String[][] result, int column, int row, String s) {
        return (result[column][row] == null ? "" : result[column][row]) + s;
    }

    private static void printArray(int[] a) {
        for (int o: a) {
            System.out.print(o+" ");
        }
        System.out.println();
    }

    private static void printArray(String[][] a) {
        for (String[] rows : a) {
            for (String column : rows) {
                System.out.print(column + " ");
            }
            System.out.print("|");
        }
        System.out.println();
    }
}
